#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>

/*
 * tool to set both the scheduling policy and the associated parameters for the process whose ID is specified in pid. 
 * used systemcall: int sched_setscheduler(pid_t pid, int policy,
 *                               const struct sched_param *param);
 */

/*
* If pid equals zero, the scheduling
* policy and parameters of the calling process will be set.  The interpretation of the argument param depends on the selected policy.  Currently,  Linux  supports  the
* following "normal" (i.e., non-real-time) scheduling policies:
* SCHED_OTHER   the standard round-robin time-sharing policy;
* SCHED_BATCH   for "batch" style execution of processes; and
* SCHED_IDLE    for running very low priority background jobs.
*
* The  following "real-time" policies are also supported, for special time-critical applications that need precise control over the way in which runnable processes are
* selected for execution:
* SCHED_FIFO    a first-in, first-out policy; and
* SCHED_RR      a round-robin policy.
*/

/*
* Scheduling Policies
* The  scheduler  is the kernel component that decides which runnable process will be executed by the CPU next.  Each process has an associated scheduling policy and a
* static scheduling priority, sched_priority; these are the settings that are modified by sched_setscheduler().  The scheduler makes it decisions based on knowledge of
* the scheduling policy and static priority of all processes on the system.
* 
* For  processes  scheduled  under one of the normal scheduling policies (SCHED_OTHER, SCHED_IDLE, SCHED_BATCH), sched_priority is not used in scheduling decisions (it
* 	must be specified as 0).
* 
* Processes scheduled under one of the real-time policies (SCHED_FIFO, SCHED_RR) have a sched_priority value in the range 1 (low) to 99 (high).  (As the numbers imply,
* 	real-time  processes  always  have  higher priority than normal processes.)  Note well: POSIX.1-2001 only requires an implementation to support a minimum 32 distinct
* priority levels for the real-time policies, and some systems supply just this minimum.  Portable programs should use sched_get_priority_min(2)  and  sched_get_prior-
* ity_max(2) to find the range of priorities supported for a particular policy.
* 
* Conceptually, the scheduler maintains a list of runnable processes for each possible sched_priority value.  In order to determine which process runs next, the sched-
* uler looks for the nonempty list with the highest static priority and selects the process at the head of this list.
* 
* A process's scheduling policy determines where it will be inserted into the list of processes with equal static priority and how it will move inside this list.
* 
* All scheduling is preemptive: if a process with a higher static priority becomes ready to run, the currently running process will be preempted and  returned  to  the
* wait list for its static priority level.  The scheduling policy only determines the ordering within the list of runnable processes with equal static priority.
*/

/*
 * On success, sched_setscheduler() returns zero.On  error,  -1  is
 * returned, and errno is set appropriately.
 * EINVAL The scheduling policy is not one of the recognized policies, or param does not make sense for the policy.
 * EPERM  The calling process does not have appropriate privileges.
 * ESRCH  The process whose ID is pid could not be found.
 */


/*
 * for kernel verison 2.6.34
 * #define	EINVAL		22	// Invalid argument 
 * #define	EPERM		 1	// Operation not permitted 
 * #define	ESRCH		 3	// No such process 
 */

int main(int argc, const char* argv[])
{       
	if(argc != 4)
	{
		printf("Usgae: %s <pid> <policy> <sched_priority>\n", argv[0]);
	        return 1;
	}
	int pid = atoi(argv[1]);
	int policy = atoi(argv[2]);
	int sched_priority = atoi(argv[3]);
	//printf("prio: %d", sched_priority);
	struct sched_param param;
        param.sched_priority = sched_priority;

	int ret = sched_setscheduler(pid, policy, &param);
	if(ret != 0)
	{
		switch(errno)
		{
			case 1:
				printf("The calling process does not have appropriate privileges.\n");
				break;
			case 3:
				printf("The process whose ID is %d could not be found.\n",pid);
				break;
			case 22:
				printf("The scheduling policy is not one of the recognized policies, or param does not make sense for the policy.\n");
				break;
			default:
				printf("errno: %d\n", errno);
				break;
		}
	}

	return 0;
} 
